package cn.ante.ymcc.mq.listner;

import cn.ante.ymcc.domain.CourseOrder;
import cn.ante.ymcc.domain.PayOrder;
import cn.ante.ymcc.dto.Order2PayDto;
import cn.ante.ymcc.dto.PayAliNotifyDto;
import cn.ante.ymcc.service.IPayNotifyService;
import cn.ante.ymcc.service.IPayOrderService;
import com.alibaba.fastjson.JSONObject;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;

import java.nio.charset.StandardCharsets;
import java.util.Map;

//@Component 因为下面的注解是组合注解，可以不加这个component
@RocketMQTransactionListener(txProducerGroup = "TxPayAliNotifyGroup")
public class AliPayTransMsgListener implements RocketMQLocalTransactionListener {
    @Autowired
    private IPayNotifyService payNotifyService;
    @Autowired
    private IPayOrderService payOrderService;
    /**
    * @Description: 执行本地事务（修改支付单状态，保存交易流水）  都应该交给事务监听器来做
     * * 要用事务消息保存本地事务和发送消息成功，必须保证原子性，所以需要将执行本地事务的操作交给事务监听器
     * 半消息应该包含什么：
    * @Author: Nai
    * @Version: 1.0
    * @Date:  2022/8/20 17:29
    */
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        if (arg == null){
            return RocketMQLocalTransactionState.ROLLBACK;
        }
        // 扩展参数中的对象，就是执行本地事务需要到的参数，将其强转为主订单对象
        Map<String,Object> map = (Map<String,Object>) arg;

        // 判断主订单对象非空，如果为空参数就不齐全，无法执行本地事务，则直接回滚
        try {
            payNotifyService.updatePayAndSaveFlow(map);
            return RocketMQLocalTransactionState.COMMIT;
        } catch (Exception e) {
            e.printStackTrace();
            return RocketMQLocalTransactionState.ROLLBACK;
        }

    }


    /**
    * @Description: 检查本地事务是否完成，当本地事务已经执行完成，但是服务器崩了，不提交状态的时候，使用该方法进行回查
    * @Author: Nai
    * @Version: 1.0
    * @Date:  2022/8/20 20:07
    */
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
        try {
            String s = new String((byte[]) msg.getPayload(), StandardCharsets.UTF_8);
            PayAliNotifyDto payAliNotifyDto = JSONObject.parseObject(s, PayAliNotifyDto.class);
            PayOrder payOrder = payOrderService.checkPayOrder(payAliNotifyDto.getOrderNo());
            // 检查本地事务时，根据单号得到的支付单不为空且该支付单胡状态为已支付完成，说明已经修改执行，提交事务即可
            if (payOrder != null && payOrder.getPayStatus() == PayOrder.STATE_SUCCESS){
                return RocketMQLocalTransactionState.COMMIT; //检查本地事务成功
            }
            return RocketMQLocalTransactionState.ROLLBACK; //检查本地事务失败回滚
        } catch (Exception e) {
            e.printStackTrace();
            return RocketMQLocalTransactionState.UNKNOWN; //捕捉异常  不知道事务
        }
    }
}
